完全二叉树或满二叉树的数组实现(参考性质5)
二叉树主要有两种实现方式,数组形式和链表形式,其中数组形式是利用完全二叉树的性质5:
性质5:如果对一棵有n个结点的完全二叉树的结点按层序编号,则对任一结点i(1in),有: (1) 如果i=1,则结点i是二叉树的根,无双亲;如果i>1,则其双亲是i/2 (2) 如果2i>n,则结点i无左孩子;如果2in,则其左孩子是2i (3) 如果2i+1>n,则结点i无右孩子;如果2i+1n,则其右孩子是2i+1
来实现的,左边的节点的下标是根节点的下标的2倍,右边的节点的下标是根节点下标的2倍加1。千万要记住这个只能用于完全二叉树(满二叉树其实就是更加完美的完全二叉树),上篇文章写的那种多杈树是用不了的,一般的二叉树也只是有的能用。。(估计很少,就当做不能用吧)。
对应树的操作我用数组实现了树的插入,删除,遍历。因为二叉树是一个完全二叉树,插入以后也要维持完全二叉树的性质,所以看来只能在数组的最后一位插入了。删除的我写了一个从中间节点删的函数,但是感觉实用价值不是很大。
这里是实现代码:
#include<stdio.h> char src[10]={0,'a','b','c','d','e','f'};//6个元素 int length(char a[]){ int ret = 1; while(a[ret]!=0){ret++;} return ret; } void insert(char data){ int srclen = length(src); src[srclen] = data; } void del(int index){ //把数组index后面的内容都往前面挪一位 int cur_l = length(src) - 1; src[index] = 0; for(int i=index;i<cur_l;i++){ src[i] = src[i+1]; } src[cur_l] = 0; } void preorder(int n){ if(n>length(src)){return;} printf("%c",src[n]); preorder(2*n); preorder(2*n+1); } void print(){ int srclength = sizeof(src)/sizeof(char); for(int i=0;i<srclength;i++){ printf("%c",src[i]); } printf("\n"); } int main(){ print(); insert('h'); print(); del(2); print(); preorder(1);//从1开始 return 0; }
sizeof(src)/sizeof(char)这个东西它始终等于的是数组开辟的个数,这里也就是一直等于10.所以不能用它来控制循环的。。。坑
大多数想法要么平庸,要么更糟糕,这很大程度上因为绝妙的想法难得一见,而且他们还要在我们身边这个充斥了各种恶俗的所谓常识的环境中孕育生长。